﻿using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Bomber.TF.Common.GDI;
using Bomber.TF.GameCenter.BomberCenter;
using Bomber.TF.GameCenter.MapCenter;

namespace Bomber.TF.GameCenter
{
    public unsafe class GameControlCenter : IDisposable
    {
        private MapBase _mapBase;
        private readonly int _mapWidth;
        private readonly int _mapHeight;
        public int MaxRow { get; set; }
        public int MaxColumn { get; set; }
        public int StartX { get; set; }
        public int StartY { get; set; }
        public int CellWidth { get; set; }
        public int CellHeight { get; set; }
        public float ZoomX { get; set; }
        public float ZoomY { get; set; }
        private readonly GameListBase[,] _set;
        private BomberBase _operateBomber;
        private readonly ImageObject _imageObjectLove;
        private ImageObject _imageGameOver;
        public GameControlCenter(int row, int column, int cellWidth, int cellHeight)
        {
            MaxRow = row;
            MaxColumn = column;
            CellWidth = cellWidth;
            CellHeight = cellHeight;
            _mapWidth = cellWidth * column;
            _mapHeight = cellHeight * row;
            _set = new GameListBase[row, column];
            _mapBase = new MapOne(row, column, _mapWidth, _mapHeight, cellWidth, cellHeight);
            _imageObjectLove = new ImageObject(Properties.Resources.love);
            Init();
        }
        private void Init()
        {
            fixed (GameListBase* set = _set)
            {
                for (int i = 0; i < MaxRow; i++)
                {
                    for (int j = 0; j < MaxColumn; j++)
                    {
                        *(set + i * MaxColumn + j) = new GameListBase();
                    }
                }
                _mapBase.CreateBlock(set);
                _operateBomber = new Bomber1();
                _operateBomber.DefaultColumn = 1;
                _operateBomber.DefaultRow = 1;
                _operateBomber.DeathCallback = DeathCallback;
                SetParameter(_operateBomber, _operateBomber.DefaultRow, _operateBomber.DefaultColumn);
                (set + 1 * MaxColumn + 1)->Games.Add(_operateBomber);
            }
        }
        bool _isDeath = false;
        private void DeathCallback(BomberBase bomberBase)
        {
            if (bomberBase != _operateBomber) return;

            _isDeath = true;
        }
        private void SetParameter(GameBase gameBase, int row, int column)
        {
            gameBase.MaxRow = this.MaxRow;
            gameBase.MaxColumn = this.MaxColumn;
            gameBase.StartX = this.StartX;
            gameBase.StartY = this.StartY;
            gameBase.CellWidth = this.CellWidth;
            gameBase.CellHeight = this.CellHeight;
            gameBase.ZoomX = this.ZoomX;
            gameBase.ZoomY = this.ZoomY;
            gameBase.Row = row;
            gameBase.Column = column;

            gameBase.UpdateLocation();
        }
        public virtual void Business()
        {
            fixed (GameListBase* set = _set)
            {
                for (int i = 0; i < MaxRow; i++)
                {
                    for (int j = 0; j < MaxColumn; j++)
                    {
                        GameListBase* ptr = set + i * MaxColumn + j;
                        if (*ptr == null) continue;
                        if (ptr->Games.Count == 0) continue;
                        for (int k = 0; k < ptr->Games.Count; k++)
                        {
                            ptr->Games[k].Business(set);
                        }
                    }
                }
            }
        }
        public void Draw(Graphics graphics)
        {
            _mapBase.Draw(graphics);
            fixed (GameListBase* set = _set)
            {
                for (int i = 0; i < MaxRow; i++)
                {
                    for (int j = 0; j < MaxColumn; j++)
                    {
                        GameListBase* ptr = set + i * MaxColumn + j;
                        if (*ptr == null) continue;
                        if (ptr->Games.Count == 0) continue;
                        for (int k = 0; k < ptr->Games.Count; k++)
                        {
                            ptr->Games[k].Draw(graphics);
                        }
                    }
                }
            }
            // 绘制爱心
            const int loveSize = 32;
            IntPtr hdc = graphics.GetHdc();
            int x = StartX + (int)(5 * ZoomX);
            int y = StartY + (int)(5 * ZoomY);
            for (int i = 0; i < _operateBomber.Life; i++)
            {
                GDI32.DrawImageTransparenc(hdc, _imageObjectLove.BitmapPtr, x, y, _imageObjectLove.Width, _imageObjectLove.Height, loveSize, loveSize);
                x += loveSize;
            }
            DrawDeath(hdc);
            graphics.ReleaseHdc(hdc);
        }
        private int _deathY = -150;
        private void DrawDeath(IntPtr hdc)
        {
            if (!_isDeath) return;

            if (_imageGameOver == null)
                _imageGameOver = new ImageObject(Properties.Resources.gameOver);
            int w = (int)(_imageGameOver.Width * ZoomX);
            int h = (int)(_imageGameOver.Height * ZoomY);
            int x = (CellWidth * MaxColumn - w) / 2;
            int y = _deathY;
            GDI32.DrawImageTransparenc(hdc, _imageGameOver.BitmapPtr, x, y, _imageGameOver.Width, _imageGameOver.Height, w, h);
            _deathY += 1;
            if (_deathY > 0)
                _deathY = 0;
        }
        public void SizeChange(int row, int column, int startX, int startY, int cellWidth, int cellHeight, float zoomX, float zoomY)
        {
            this.MaxRow = row;
            this.MaxColumn = column;
            this.StartX = startX;
            this.StartY = startY;
            this.CellWidth = cellWidth;
            this.CellHeight = cellHeight;
            this.ZoomX = zoomX;
            this.ZoomY = zoomY;
            _mapBase.SizeChange(row, column, startX, startY, cellWidth, cellHeight, zoomX, zoomY);
            fixed (GameListBase* set = _set)
            {
                for (int i = 0; i < MaxRow; i++)
                {
                    for (int j = 0; j < MaxColumn; j++)
                    {
                        GameListBase* ptr = set + i * MaxColumn + j;
                        if (ptr->Games.Count == 0) continue;
                        for (int k = 0; k < ptr->Games.Count; k++)
                        {
                            ptr->Games[k].SizeChange(row, column, startX, startY, cellWidth, cellHeight, zoomX, zoomY);
                        }
                    }
                }
            }
        }
        public void ProcessCmdKeyUp()
        {
            fixed (GameListBase* set = _set)
            {
                _operateBomber.Up(set);
            }
        }
        public void ProcessCmdKeyDown()
        {
            fixed (GameListBase* set = _set)
            {
                _operateBomber.Down(set);
            }
        }
        public void ProcessCmdKeyLeft()
        {
            fixed (GameListBase* set = _set)
            {
                _operateBomber.Left(set);
            }
        }
        public void ProcessCmdKeyRight()
        {
            fixed (GameListBase* set = _set)
            {
                _operateBomber.Right(set);
            }
        }
        public void ProcessCmdKeySpace()
        {
            fixed (GameListBase* set = _set)
            {
                _operateBomber.Space(set);
            }
        }
        public void Dispose()
        {
            fixed (GameListBase* set = _set)
            {
                for (int i = 0; i < MaxRow; i++)
                {
                    for (int j = 0; j < MaxColumn; j++)
                    {
                        GameListBase* ptr = set + i * MaxColumn + j;
                        if (ptr->Games.Count == 0) continue;
                        for (int k = 0; k < ptr->Games.Count; k++)
                        {
                            ptr->Games[k].Dispose();
                        }
                    }
                }
            }
            _imageObjectLove.Dispose();
            _mapBase.Dispose();
            _operateBomber.Dispose();
            _imageGameOver?.Dispose();
        }
    }
}
